package com.edroid.droidhelper.pc.model;

import java.awt.Image;
import java.awt.image.BufferedImage;

import javax.swing.SwingUtilities;

import com.android.ddmlib.IDevice;
import com.android.ddmlib.IDevice.DeviceState;
import com.android.ddmlib.RawImage;
import com.edroid.droidhelper.pc.model.IInstallTask.OnProgUpdateListener;
import com.edroid.droidhelper.pc.util.Logger;

public class Phone implements IPhone {
	static Logger log = Logger.create("EDevice");
	
	public static int STATE_UNAVAILABLE = 0;
	public static int STATE_AVAILABEL = 1;
	
	private IDevice mDevice;
	private String imei = "null";
	private String name;
	private String model, manufacturer, hardware, release, hostname;
	private BufferedImage image;
	private IInstallTask installTask;
	
	
	public Phone(IDevice device) {
		mDevice = device;
		installTask = new InstallTask(this);
		
		if(mDevice.getState() == DeviceState.ONLINE) {
			getInfos();
			
			startInstallTask();
		}
	}
	
	@Override
	public void startInstallTask() {
		installTask.start();
	}

	@Override
	public void stopInstallTask(boolean waitForFinish) {
		installTask.stop(waitForFinish);
	}
	
	public boolean isAvailable() {
		if(mDevice == null)
			return false;
		
		return (mDevice.getState() == DeviceState.ONLINE);
	}
	
	public String getDeviceState() {
		if(mDevice == null)
			return "DISCONNECTED";
		
		return mDevice.getState().toString();
	}
	
	/**
	 * 获取系统数据 getprop
	 * @param key
	 * @return
	 */
	public String getProp(String key) {
		try {
			return cleanupStringForDisplay(mDevice.getPropertyCacheOrSync(key));
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		return null;
	}
	
	public void installApk(String apkPath) throws Exception {
		mDevice.installPackage(apkPath, true);
	}
	
	public void setOnProgUpdateListener(OnProgUpdateListener listener) {
		installTask.setOnProgUpdateListener(listener);
	}
	
	private void getInfos() {
//		do_shell("dumpsys iphonesubinfo");
//		mDevice.pushFile(local, remote);

		model = getProp("ro.product.model");
		manufacturer = getProp("ro.product.manufacturer");
		hardware = getProp("ro.hardware");
		release = getProp("ro.build.version.release");
		hostname = getProp("net.hostname");
		
		runShellCommond(new ShellCommand("dumpsys iphonesubinfo", new ShellCommand.CommandResultReceiver() {
			
			@Override
			public void onSuc(String ret) {
				String[] ss = ret.split("=");
				if(ss != null && ss.length > 1) {
					imei = ss[2].trim();
					log.i("imei: " + imei);
				}
			}
			
			@Override
			public void onFail(Exception e) {
				e.printStackTrace();
			}
		}));
	}
	
	@Override
	public void onStateChanged(IDevice iDevice, int mask) {
		if(mask == IDevice.CHANGE_STATE) {
			if(iDevice.getState() == DeviceState.ONLINE) {
				getInfos();
				
				startInstallTask();
			}
		}
	}

	@Override
	public void onDisconnect() {
		installTask.stop(false);
	}
	
	private String cleanupStringForDisplay(String s) {
		if (s == null) {
			return null;
		}
		StringBuilder sb = new StringBuilder(s.length());
		for (int i = 0; i < s.length(); i++) {
			char c = s.charAt(i);
			if (Character.isLetterOrDigit(c)) {
				sb.append(Character.toLowerCase(c));
			} else {
				sb.append('_');
			}
		}
		return sb.toString();
	}
	
	public void runShellCommond(ShellCommand cmd) {
		try {
			mDevice.executeShellCommand(cmd.getCmd(), cmd);
		} catch (Exception e) {
			cmd.onException(e);
		}
	}
	
	@Override
	public String toString() {
		return getName();
	}
	
	public String getName() {
		if(name == null)
			name = (manufacturer + "-" + model + "-" + mDevice.getSerialNumber());
		return name;
	}
	
	public String getModel() {
		return model;
	}
	
	public String getManufacturer() {
		return manufacturer;
	}
	
	public String getImei() {
		return imei;
	}
	
	public String getHardware() {
		return hardware;
	}
	
	public interface FetchScreenshotCallback {
		
		public void onSuc(Image image);
		
		public void onFail(Exception e);
 	}
	
	public void fetchScreenshot(final FetchScreenshotCallback cb) {
		if(mDevice == null) {
			cb.onFail(new NullPointerException("null device"));
			return;
		}
		
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				fetchScreenshotRun(cb);
			}
		}).start();
	}
	
	private void fetchScreenshotRun(final FetchScreenshotCallback cb) {
		// System.out.println("Getting initial screenshot through ADB");
		RawImage rawImage = null;
		
		synchronized (mDevice) {
			try {
				rawImage = mDevice.getScreenshot();
			} catch (Exception e) {
				cb.onFail(e);

				e.printStackTrace();
			}
		}

		if (rawImage != null) {
			boolean landscape = false;
			
			// System.out.println("screenshot through ADB ok");
			int width2 = landscape ? rawImage.height : rawImage.width;
			int height2 = landscape ? rawImage.width : rawImage.height;
			
			if (image == null) {
				image = new BufferedImage(width2, height2,
						BufferedImage.TYPE_INT_RGB);
//				size.setSize(image.getWidth(), image.getHeight());
			} else {
				if (image.getHeight() != height2 || image.getWidth() != width2) {
					image = new BufferedImage(width2, height2,
							BufferedImage.TYPE_INT_RGB);
//					size.setSize(image.getWidth(), image.getHeight());
				}
			}
			
			int index = 0;
			int indexInc = rawImage.bpp >> 3;
			for (int y = 0; y < rawImage.height; y++) {
				for (int x = 0; x < rawImage.width; x++, index += indexInc) {
					int value = rawImage.getARGB(index);
					if (landscape)
						image.setRGB(y, rawImage.width - x - 1, value);
					else
						image.setRGB(x, y, value);
				}
			}

			if (cb != null) {
				SwingUtilities.invokeLater(new Runnable() {

					public void run() {
						cb.onSuc(image);
					}
				});
			}
		} else {
			log.i("failed getting screenshot through ADB ok");
		}
	}

	@Override
	public String getOsVer() {
		return release;
	}

	@Override
	public String getHostName() {
		return hostname;
	}
}
